<template>
  <div>
    <el-card class="box-card">
      <el-dropdown style="float:right;" @command="actionHandleFolderOperation" trigger="click">
        <span class="el-dropdown-link"> 
          <i class="el-icon-s-operation"></i> 
          <i class="el-icon-arrow-down el-icon--right"></i> 
        </span>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item :command="{action:'NewFolder'}">新建文件夹</el-dropdown-item>
          <el-dropdown-item :command="{action:'NewFile'}">新建文件</el-dropdown-item>
          <el-dropdown-item :command="{action:'Upload'}">上传文件</el-dropdown-item>
          <el-dropdown-item :command="{action:'Refresh'}">刷新</el-dropdown-item>
          <el-dropdown-item v-if="'list' != viewMode" :command="{action:'ViewModeList'}">列表视图</el-dropdown-item>
          <el-dropdown-item v-if="'grid' != viewMode" :command="{action:'ViewModeGrid'}">方格视图</el-dropdown-item>
          <el-dropdown-item v-if="!showHide" :command="{action:'ShowHiddenFiles'}">显示隐藏文件</el-dropdown-item>
          <el-dropdown-item v-if="showHide" :command="{action:'HideHiddenFiles'}">不显示隐藏文件</el-dropdown-item>
          <el-dropdown-item :command="{action:'OpenTerminal'}">打开终端</el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
      <el-breadcrumb separator="/">
        <el-breadcrumb-item @click.native="actionGoToRoot()"
        ><i class="el-icon-house cursor-pointer"></i></el-breadcrumb-item>
        <el-breadcrumb-item v-for="(item,index) in path" :key="item" 
          @click.native="actionGoToPathItem(index)"
        ><span class="cursor-default">{{item}}</span></el-breadcrumb-item>
      </el-breadcrumb>
    </el-card>
    <card-file-list-viewer 
      :files="files" 
      :mode="viewMode"
      @file-delete="actionHandleFileDelete"
      @file-rename="actionHandleFileRename"
      @file-download="actionHandleFileDownload"
      @file-click="actionHandleFileClick"
      @folder-click="actionHandleFolderClick"
      @file-text-edit="actionHandleFileTextEdit"
    ></card-file-list-viewer>
    
    <dialog-terminal ref="dialogTerminal"></dialog-terminal>
    <file-text-editor ref="textEditor"></file-text-editor>
    <dialog-file-download ref="dialogFileDownload"></dialog-file-download>
    <dialog-file-upload ref="dialogFileUpload" @uploaded="actionRefreshList"></dialog-file-upload>
  </div>
</template>
<script>
import FileOpenHandlerMap from './FileOpenHandlerMap.js'
import FileTextEditor from './FileTextEditor.vue'
import DialogFileDownload from './DialogFileDownload.vue'
import DialogFileUpload from './DialogFileUpload.vue'
import CardFileListViewer from './CardFileListViewer.vue'
import DialogTerminal from './DialogTerminal.vue'
export default {
    name : 'FileManagement',
    components : {
        'file-text-editor' : FileTextEditor,
        'dialog-file-download' : DialogFileDownload,
        'dialog-file-upload' : DialogFileUpload,
        'card-file-list-viewer' : CardFileListViewer,
        'dialog-terminal' : DialogTerminal,
    },
    data() {
        return {
            ssh : null,
            sftp : null,
            path : [],
            files : [],
            showHide : false,
            viewMode : 'grid',
        };
    },
    async mounted() {
        let server = this.$store.getters.serverCurrent;
        this.ssh = await server.getSshClient();

        let home = await this.ssh.exec('cd ~ && pwd');
        home = home.trim().substr(1);
        this.path = home.split('/');
        
        this.sftp = await this.ssh.getSftp();
        this.actionRefreshList();
    },
    destroyed() {
        this.sftp.end();
    },
    methods : {
        // 文本编辑
        actionHandleFileTextEdit( file ) {
            let filepath = this.path.slice();
            filepath.push(file.filename);
            filepath = '/' + filepath.join('/');
            this.$refs.textEditor.open(filepath);
        },

        // 文件删除
        async actionHandleFileDelete( file ) {
            try {
                await this.$confirm(`此操作将永久删除 ${file.filename}, 是否继续?`, '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                });
            } catch {
                return;
            }

            let path = JSON.parse(JSON.stringify(this.path));
            path.push(file.filename);
            path = '/' + path.join('/');

            let server = this.$store.getters.serverCurrent;
            try {
                if ( file.attrs.isDirectory() ) {
                    await server.dirRemove(path);
                } else {
                    await server.fileRemove(path);
                }
            } catch ( error ) {
                console.log(error);
                this.$message.error(error.message);
                return;
            }
            
            this.actionRefreshList();
        },

        // 文件重命名
        async actionHandleFileRename( file ) {
            let newName = null;
            try {
                newName = await this.$prompt('请输入新名称', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    inputValue : file.filename,
                });
            } catch {
                return;
            }

            let oldpath = this.path.slice();
            oldpath.push(file.filename);
            oldpath = '/' + oldpath.join('/');

            let newpath = this.path.slice();
            newpath.push(newName.value);
            newpath = '/' + newpath.join('/');

            let server = this.$store.getters.serverCurrent;
            try {
                await server.fileRename(oldpath, newpath);
            } catch ( error ) {
                console.log(error);
                this.$message.error(error.message);
                return;
            }

            this.actionRefreshList();
        },

        // 文件下载
        async actionHandleFileDownload( file ) {
            this.$refs.dialogFileDownload.start(this.path, file);
        },

        // 文件点击
        actionHandleFileClick ( file ) {
            let filepath = this.path.slice();
            filepath.push(file.filename);
            filepath = '/' + filepath.join('/');
            
            let handlerName = FileOpenHandlerMap.getHandlerName(file.filename);
            if ( 'text-editor' == handlerName ) {
                this.$refs.textEditor.open(filepath);
            } else {
                let $this = this;
                this.$confirm('无法打开该类型文件，是否下载到本地?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    $this.actionHandleFileDownload(file);
                }).catch(() => {});
            }
        },

        // 文件夹点击
        actionHandleFolderClick( file ) {
            this.path.push(file.filename);
            this.actionRefreshList();
        },

        // 执行该目录操作
        actionHandleFolderOperation( cmd ) {
            let handler = `handleFolderOperation${cmd.action}`;
            this[handler]();
        },

        // 上传文件
        handleFolderOperationUpload() {
            this.$refs.dialogFileUpload.start(this.path);
        },

        // 新建文件夹
        async handleFolderOperationNewFolder() {
            let newName = null;
            try {
                newName = await this.$prompt('请输入文件夹名称', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    inputValue : '',
                });
            } catch {
                return;
            }

            let path = this.path.slice();
            path.push(newName.value);
            path = '/' + path.join('/');

            let cmd = `mkdir ${path}`;
            await this.ssh.exec(cmd);
            this.actionRefreshList();
        },

        // 新建文件夹
        async handleFolderOperationNewFile() {
            let newName = null;
            try {
                newName = await this.$prompt('请输入文件名称', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    inputValue : '',
                });
            } catch {
                return;
            }

            let path = this.path.slice();
            path.push(newName.value);
            path = '/' + path.join('/');

            let cmd = `touch ${path}`;
            await this.ssh.exec(cmd);
            this.actionRefreshList();
        },

        // 切换到列表视图
        handleFolderOperationViewModeList() {
            this.viewMode = 'list';
        },

        // 切换到方格视图
        handleFolderOperationViewModeGrid() {
            this.viewMode = 'grid';
        },

        // 显示隐藏文件
        handleFolderOperationShowHiddenFiles() {
            this.showHide = true;
            this.actionRefreshList();
        },

        // 不显示隐藏文件
        handleFolderOperationHideHiddenFiles() {
            this.showHide = false;
            this.actionRefreshList();
        },

        // 打开终端
        handleFolderOperationOpenTerminal() {
            let pwd = '/' + this.path.join('/');
            this.$refs.dialogTerminal.open(pwd);
        },

        // 刷新列表
        handleFolderOperationRefresh() {
            this.actionRefreshList();
        },

        // 刷新列表
        actionRefreshList() {
            let path = '/' + this.path.join('/');
            
            let $this = this;
            $this.files = [];
            this.sftp.readdir(path, (err, list) => {
                if (err) throw err;
                let files = [];
                for ( let i=0; i<list.length; i++ ) {
                    if ( !$this.showHide && '.' == list[i].filename[0] ) {
                        continue;
                    }
                    files.push(list[i]);
                }
                
                files.sort($this.fileSort);
                $this.files = files;
            });
        },

        // 文件排序
        fileSort( fileA, fileB ) {
            let fileAType = fileA.attrs.isDirectory();
            let fileBType = fileB.attrs.isDirectory();
            if ( fileBType != fileAType ) {
                return fileBType - fileAType;
            }
            
            return fileA.filename.localeCompare(fileB.filename);
        },

        // 跳转到指定目录索引
        actionGoToPathItem(index) {
            this.path = this.path.slice(0, index+1);
            this.actionRefreshList();
        },

        // 跳转到根目录
        actionGoToRoot() {
            this.path = [];
            this.actionRefreshList();
        },
    }
}
</script>